package com.example.ddz.framework.impl;

/**
 * Created by IntelliJ IDEA.
 * User: Marcel Melzig
 * Date: 20.07.11
 * Time: 20:50
 */

import java.io.IOException;

import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;

import com.example.ddz.framework.IMusic;

/**
 * This class defines an Music object. That is a sound file with a length of a few seconds up to minutes.
 */
public class Music implements IMusic, OnCompletionListener
{
    private final MediaPlayer mediaPlayer;
    private boolean isPrepared = false;

    /**
     * Instantiates an instance of the Music class.
     *
     * @param assetDescriptor An descriptor which defines a file in the assets folder.
     */
    public Music(AssetFileDescriptor assetDescriptor)
    {
        mediaPlayer = new MediaPlayer();
        try
        {
            mediaPlayer.setDataSource(assetDescriptor.getFileDescriptor(), assetDescriptor.getStartOffset(), assetDescriptor.getLength());
            mediaPlayer.prepare();
            isPrepared = true;
            mediaPlayer.setOnCompletionListener(this);
        }
        catch (Exception e)
        {
            throw new RuntimeException("Couldn't load music");
        }
    }

    /**
     * Disposes this instance and releases the resources.
     */
    @Override
    public void Dispose()
    {
        if (mediaPlayer.isPlaying())
            mediaPlayer.stop();
        mediaPlayer.release();
    }

    /**
     * Returns the looping state.
     *
     * @return True if the music file is looping, otherwise false.
     */
    @Override
    public boolean IsLooping()
    {
        return mediaPlayer.isLooping();
    }

    /**
     * Returns the playback state.
     *
     * @return True if the music is playing, otherwise false.
     */
    @Override
    public boolean IsPlaying()
    {
        return mediaPlayer.isPlaying();
    }

    /**
     * Returns a state describing if the music is stopped or not.
     *
     * @return True if the music playback is stopped, otherwise false.
     */
    @Override
    public boolean IsStopped()
    {
        return !isPrepared;
    }

    /**
     * Starts the music playback if it isn't already started.
     */
    @Override
    public void Play()
    {
        if (mediaPlayer.isPlaying())
            return;

        try
        {
            synchronized (this)
            {
                if (!isPrepared)
                    mediaPlayer.prepare();
                mediaPlayer.start();
            }
        }
        catch (IllegalStateException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    /**
     * Pauses the playback.
     */
    @Override
    public void Pause()
    {
        if (!mediaPlayer.isPlaying())
            return;

        try
        {
            mediaPlayer.pause();
        }
        catch (IllegalStateException e)
        {
            e.printStackTrace();
        }
    }

    /**
     * Sets the music to looping mode.
     *
     * @param isLooping True if the music should be looped, otherwise false.
     */
    @Override
    public void SetLooping(boolean isLooping)
    {
        mediaPlayer.setLooping(isLooping);
    }

    /**
     * Sets the volume.
     *
     * @param volume The volume.
     */
    @Override
    public void SetVolume(float volume)
    {
        mediaPlayer.setVolume(volume, volume);
    }

    /**
     * Stops the music playback.
     */
    @Override
    public void Stop()
    {
        mediaPlayer.stop();
        synchronized (this)
        {
            isPrepared = false;
        }
    }

    /**
     * Sets the isPrepares field to false to prevent other methods from throwing exceptions out of the blue.
     *
     * @param player The current MediaPlayer instance.
     */
    @Override
    public void onCompletion(MediaPlayer player)
    {
        synchronized (this)
        {
            isPrepared = false;
        }
    }
}
